home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / editres / utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-12  |  23.7 KB  |  912 lines

  1. /*
  2.  * $XConsortium: utils.c,v 1.17 91/10/09 10:39:44 dave Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. #ifdef MSDOS
  25. #include "X11/Intrinsc.h"      /* QDK 05/11/1994 12:54pm. */
  26. #else
  27. #include "X11/Intrinsic.h"
  28. #endif
  29. #include <X11/Xutil.h>
  30. #include <X11/Xos.h>
  31. #include <X11/Shell.h>
  32. #include <X11/StringDefs.h>
  33.  
  34. #include <X11/Xaw/Cardinals.h>
  35. #include <X11/Xaw/Dialog.h>
  36.  
  37. #include <stdio.h>
  38.  
  39. #include "editresP.h"
  40.  
  41. static WidgetResources * ParseResources();
  42. static int CompareResourceEntries();
  43. static void FreeResources(), AddResource();
  44. static WNode * FindWidgetFromWindowGivenNode();
  45.  
  46. void CreateResourceBox();
  47.  
  48. extern void PopupCentered(), PerformTreeToFileDump();
  49.  
  50. /*    Function Name: ShowMessage(w, str)
  51.  *    Description: shows the message to the user.
  52.  *    Arguments: w - a label widget to show the message in.
  53.  *                 str - the string to show.
  54.  *    Returns: none.
  55.  */
  56.  
  57. void
  58. SetMessage(w, str)
  59. Widget w;
  60. char * str;
  61. {
  62.     Arg args[1];
  63.  
  64.     XtSetArg(args[0], XtNlabel, str);
  65.     XtSetValues(w, args, ONE);
  66. }
  67.  
  68. /*    Function Name: GetAllStrings
  69.  *    Description: Returns a list of strings that have been borken up by
  70.  *                   the character specified.
  71.  *    Arguments: in - the string to parse.
  72.  *                 sep - the separator character.
  73.  *                 out - the strings to send out.
  74.  *                 num - the number of strings in out.
  75.  *    Returns: none
  76.  */
  77.  
  78. void
  79. GetAllStrings(in, sep, out, num)
  80. char *in, sep, ***out;
  81. int * num;
  82. {
  83.     int size, i;
  84.     char * ptr;
  85.  
  86.     if (*in == sep)        /* jump over first char if it is the sep. */
  87.     in++;
  88.  
  89.     /*
  90.      * count the number of strings.
  91.      */
  92.  
  93.     for (*num = 1, ptr = in; (ptr = index(ptr, sep)) != NULL; (*num)++)
  94.     ptr++;
  95.  
  96. /*
  97.  * Create Enough space for pointers and string.
  98.  */
  99.  
  100.     size = (sizeof(char *) * *num) + (sizeof(char) * (strlen(in) + 1));
  101.     *out = (char **) XtMalloc( (Cardinal) size);
  102.  
  103.     ptr = (char *) (*out + *num);
  104.     strcpy(ptr, in);
  105.  
  106. /*
  107.  * Change all `sep' characters to '\0' and stuff the pointer into
  108.  * the next pointer slot.
  109.  */
  110.  
  111.     i = 1;
  112.     (*out)[0] = ptr;
  113.     while (TRUE) {
  114.     if ((ptr = index(ptr, sep)) == NULL)
  115.         break;
  116.  
  117.     *ptr++ = '\0';
  118.     (*out)[i++] = ptr;
  119.     }
  120.  
  121. /*
  122.  * If last string is empty then strip it off.
  123.  */
  124.  
  125.     if ( *((*out)[i - 1]) == '\0' )
  126.     (*num)--;
  127. }
  128.  
  129. /*    Function Name: AddString
  130.  *    Description: Mallocs and strcats the string onto the end of
  131.  *                   the given string.
  132.  *    Arguments: str - string to add on to.
  133.  *                 add - string to add.
  134.  *    Returns: none.
  135.  */
  136.  
  137. void
  138. AddString(str, add)
  139. char ** str, *add;
  140. {
  141.     int len_str, len_add;
  142.     char * ptr;
  143.  
  144.     len_str = ((*str) ? strlen(*str) : 0);
  145.     len_add = strlen(add);
  146.  
  147.     *str = XtRealloc(*str, sizeof(char) * (len_str + len_add + 1));
  148.     ptr = *str + len_str;
  149.     strcpy(ptr, add);
  150. }
  151.  
  152. /*    Function Name: FindNode
  153.  *    Description: Finds a node give the top node, and a node id number.
  154.  *    Arguments: top_node - the top node.
  155.  *                 id - the node id.
  156.  *    Returns: node.
  157.  */
  158.  
  159. WNode *
  160. FindNode(top_node, ids, number)
  161. WNode *top_node;
  162. unsigned long * ids;
  163. Cardinal number;
  164. {
  165.     int i, j;
  166.     WNode *node;
  167.  
  168.     if (top_node == NULL)
  169.     return(NULL);
  170.  
  171.     if (ids[0] != top_node->id)
  172.     return(NULL);
  173.  
  174.     for (node = top_node, i = 1 ; i < number; i++) {
  175.     Boolean found_it = FALSE;
  176.  
  177.     for (j = 0; j < node->num_children; j++) {
  178.         if (node->children[j]->id == ids[i]) {
  179.         node = node->children[j];
  180.         found_it = TRUE;
  181.         break;
  182.         }
  183.     }
  184.     if (!found_it)
  185.         return(NULL);
  186.     }        
  187.     return(node);
  188. }
  189.  
  190. /*    Function Name: FindWidgetFromWindow
  191.  *    Description: finds a widget in the current tree given its window id.
  192.  *    Arguments: tree_info - information about this tree.
  193.  *                 win - window to search for.
  194.  *    Returns: node - the node corrosponding to this widget.
  195.  */
  196.  
  197. WNode * 
  198. FindWidgetFromWindow(tree_info, win)
  199. TreeInfo * tree_info;
  200. Window win;
  201. {
  202.     if (tree_info == NULL)
  203.     return(NULL);
  204.  
  205.     return(FindWidgetFromWindowGivenNode(tree_info->top_node, win));
  206. }
  207.  
  208. /*    Function Name: FindWidgetFromWindowGivenNode
  209.  *    Description: finds a widget in the current tree given its window id.
  210.  *    Arguments: node - current node.
  211.  *                 win - window to search for.
  212.  *    Returns: node - the node corrosponding to this widget.
  213.  */
  214.  
  215. static WNode *
  216. FindWidgetFromWindowGivenNode(node, win)
  217. WNode * node;
  218. Window win;
  219. {
  220.     int i;
  221.     WNode * ret_node;
  222.  
  223.     if (node->window == win)
  224.     return(node);
  225.  
  226.     for (i = 0; i < node->num_children; i++) {
  227.     ret_node = FindWidgetFromWindowGivenNode(node->children[i], win);
  228.     if (ret_node != NULL)
  229.         return(ret_node);
  230.     }
  231.     return(NULL);
  232. }
  233.  
  234. /*    Function Name: HandleXErrors
  235.  *    Description: Handles error codes from the server.
  236.  *    Arguments: display - the display.
  237.  *                 error - error information.
  238.  *    Returns: none.
  239.  */
  240.  
  241. /* ARGSUSED */
  242. int
  243. HandleXErrors(display, error)
  244. Display * display;
  245. XErrorEvent * error;
  246. {
  247.     if (error->serial != global_serial_num) {
  248.     (*global_old_error_handler) (display, error);
  249.     return(0);
  250.     }
  251.  
  252.     if (error->error_code == BadWindow)
  253.     global_error_code = NO_WINDOW;    
  254.     else {
  255.     if (XmuPrintDefaultErrorMessage(display, error, stderr) != 0)
  256.         exit(1);
  257.     }
  258.     return(0);
  259. }
  260.  
  261. /*    Function Name: _DumpTreeToFile
  262.  *    Description: Dumps the widget tree to a file
  263.  *    Arguments: w - a random widget in the application on the
  264.  *                     currently active display
  265.  *                 tree_ptr - pointer to the widget tree info.
  266.  *                 filename - name of the file.
  267.  *    Returns: none.
  268.  */
  269.  
  270. /* ARGSUSED */
  271.  
  272. void
  273. _DumpTreeToFile(w, tree_ptr, filename)
  274. Widget w;
  275. XtPointer tree_ptr;
  276. char * filename;
  277. {
  278.     TreeInfo * tree_info = (TreeInfo *) tree_ptr;
  279.     FILE * fp; 
  280.  
  281.     if (tree_info == NULL) {
  282.     SetMessage(global_screen_data.info_label,
  283.            "No widget Tree is avaliable.");
  284.     return;
  285.     }
  286.  
  287.     if ( (fp = fopen(filename, "w")) == NULL ) {
  288.     char buf[BUFSIZ];
  289.  
  290.     sprintf(buf, "Unable to open the file `%s' for writing.", filename);
  291.     SetMessage(global_screen_data.info_label, buf);
  292.     return;
  293.     }
  294.  
  295.     PerformTreeToFileDump(tree_info->top_node, 0, fp);
  296.     fclose(fp);
  297. }
  298.  
  299. /************************************************************
  300.  * 
  301.  * The file dialog boxes are handled with this code.
  302.  *
  303.  * It automatically calls the function specified when the
  304.  * user selects okay, or hits <CR>.
  305.  *
  306.  * A translation is required in the app-defaults file.
  307.  *
  308.  ************************************************************/
  309.  
  310. /*    Function Name: _PopupFileDialog
  311.  *    Description: Puts up a dialog box to get the filename.
  312.  *    Arguments: str - message.
  313.  *                 default_value - the default value of the filename;
  314.  *                 func - function to call when filename has been entered.
  315.  *                 data - generic data to pass to func.
  316.  *    Returns: none
  317.  */
  318.  
  319. static XContext file_dialog_context = None;
  320.  
  321. typedef struct _FileDialogInfo {
  322.     void (*func)();
  323.     XtPointer data;
  324. } FileDialogInfo;
  325.  
  326. void
  327. _PopupFileDialog(w, str, default_value, func, data)
  328. Widget w;
  329. String str, default_value;
  330. void (*func)();
  331. XtPointer data;
  332. {
  333.     FileDialogInfo * file_info;
  334.     Widget shell, dialog;
  335.     Arg args[2];
  336.     Cardinal num_args;
  337.     void _PopdownFileDialog();
  338.  
  339.     if (file_dialog_context == None)
  340.     file_dialog_context = XUniqueContext();
  341.  
  342.     shell = XtCreatePopupShell("fileDialog", transientShellWidgetClass, w,
  343.                    NULL, ZERO);
  344.  
  345.     num_args = 0;
  346.     XtSetArg(args[num_args], XtNlabel, str); num_args++;
  347.     XtSetArg(args[num_args], XtNvalue, default_value); num_args++;
  348.     dialog = XtCreateManagedWidget("dialog", dialogWidgetClass, 
  349.                    shell, args, num_args);
  350.  
  351.     file_info = XtNew(FileDialogInfo);
  352.  
  353.     file_info->func = func;
  354.     file_info->data = data;
  355.  
  356.     if  (XSaveContext(XtDisplay(dialog), (Window) dialog, file_dialog_context, 
  357.               (caddr_t) file_info) != 0) {
  358.     SetMessage(global_screen_data.info_label,
  359.         "Error while trying to save Context\nAborting file dialog popup.");
  360.     XtDestroyWidget(shell);
  361.     return;
  362.     }
  363.  
  364.     XawDialogAddButton(dialog, "okay", _PopdownFileDialog, (XtPointer) TRUE);
  365.     XawDialogAddButton(dialog, "cancel", _PopdownFileDialog,(XtPointer) FALSE);
  366.  
  367.     PopupCentered(NULL, shell, XtGrabNone);
  368. }
  369.  
  370. /*    Function Name: PopupCentered
  371.  *    Description: Pops up the window specified under the location passed
  372.  *                   in the event, or under the cursor.
  373.  *    Arguments: event - the event that we should use.
  374.  *                 w - widget to popup.
  375.  *                 mode - mode to pop it up in.
  376.  *    Returns: none
  377.  */
  378.  
  379. void
  380. PopupCentered(event, w, mode)
  381. XEvent * event;
  382. Widget w;
  383. XtGrabKind mode;
  384. {
  385.     Boolean get_from_cursor = FALSE;
  386.     Arg args[3];
  387.     Cardinal num_args;
  388.     Dimension width, height, b_width;
  389.     int x, y, max_x, max_y;
  390.  
  391.     XtRealizeWidget(w);
  392.  
  393.     if (event == NULL)
  394.     get_from_cursor = TRUE;
  395.     else {
  396.     switch (event->type) {
  397.     case ButtonPress:
  398.     case ButtonRelease:
  399.         x = event->xbutton.x_root;
  400.         y = event->xbutton.y_root;
  401.         break;
  402.     case KeyPress:
  403.     case KeyRelease:
  404.         x = event->xkey.x_root;
  405.         y = event->xkey.y_root;
  406.         break;
  407.     default:
  408.         get_from_cursor = TRUE;
  409.         break;
  410.     }
  411.     }
  412.  
  413.     if (get_from_cursor) {
  414.     Window root, child;
  415.     int win_x, win_y;
  416.     unsigned int mask;
  417.     
  418.     XQueryPointer(XtDisplay(w), XtWindow(w),
  419.               &root, &child, &x, &y, &win_x, &win_y, &mask);
  420.     }
  421.  
  422.     num_args = 0;
  423.     XtSetArg(args[num_args], XtNwidth, &width); num_args++;
  424.     XtSetArg(args[num_args], XtNheight, &height); num_args++;
  425.     XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
  426.     XtGetValues(w, args, num_args);
  427.  
  428.     width += 2 * b_width;
  429.     height += 2 * b_width;
  430.  
  431.     x -= ((int) width/2);
  432.     if (x < 0) 
  433.     x = 0;
  434.     if ( x > (max_x = (int) (XtScreen(w)->width - width)) )
  435.     x = max_x;
  436.  
  437.     y -= ( (Position) height/2 );
  438.     if (y < 0) 
  439.     y = 0;
  440.     if ( y > (max_y = (int) (XtScreen(w)->height - height)) )
  441.     y = max_y;
  442.   
  443.     num_args = 0;
  444.     XtSetArg(args[num_args], XtNx, x); num_args++;
  445.     XtSetArg(args[num_args], XtNy, y); num_args++;
  446.     XtSetValues(w, args, num_args);
  447.  
  448.     XtPopup(w, mode);
  449. }
  450.  
  451. /*    Function Name: _PopdownFileDialog
  452.  *    Description: Destroys the file dialog, and calls the correct function.
  453.  *    Arguments:  w - a child of the dialog widget.
  454.  *                  client_data - TRUE if command was sucessful.
  455.  *                  junk - ** UNUSED **.
  456.  *    Returns: none.
  457.  */
  458.  
  459. /* ARGSUSED */
  460.  
  461. void 
  462. _PopdownFileDialog(w, client_data, junk)
  463. Widget w;
  464. XtPointer client_data, junk;
  465. {
  466.     Widget dialog = XtParent(w);
  467.     caddr_t file_info_ptr;
  468.     FileDialogInfo * file_info;
  469.  
  470.     if (XFindContext(XtDisplay(dialog), (Window) dialog, file_dialog_context,
  471.              &file_info_ptr) == XCNOENT) {
  472.     SetMessage(global_screen_data.info_label,    
  473.            "Error while trying to find Context\nAborting...");    
  474.     }
  475.  
  476.     (void) XDeleteContext(XtDisplay(dialog), (Window)dialog, 
  477.               file_dialog_context);
  478.  
  479.     file_info = (FileDialogInfo *) file_info_ptr;
  480.  
  481.     if ( ((Boolean) client_data) == TRUE ) {
  482.     String filename = XawDialogGetValueString(dialog);
  483.  
  484.     (*file_info->func)(w, file_info->data, filename); /* call handler */
  485.     }
  486.  
  487.     XtFree( (XtPointer) file_info); /* Free data. */
  488.  
  489.     XtPopdown(XtParent(dialog));
  490.     XtDestroyWidget(XtParent(dialog)); /* Remove file dialog. */
  491. }
  492.  
  493. /************************************************************
  494.  *
  495.  * Functions for dealing with the Resource Box.
  496.  *
  497.  ************************************************************/
  498.  
  499. /*    Function Name: GetNamesAndClasses
  500.  *    Description: Gets a list of names and classes for this widget.
  501.  *    Arguments: node - this widget's node.
  502.  *                 names, classes - list of names and classes. ** RETURNED **
  503.  *    Returns: none.
  504.  */
  505.  
  506. void
  507. GetNamesAndClasses(node, names, classes)
  508. WNode * node;
  509. char *** names, ***classes;
  510. {
  511.     int i, total_widgets;
  512.     WNode * temp = node;
  513.  
  514.     for (total_widgets = 1 ; temp->parent != NULL ;
  515.        total_widgets++, temp = temp->parent) { } /* empty for */
  516.  
  517.     *names = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
  518.     *classes = (char **) XtMalloc(sizeof(char *) * (total_widgets + 1));
  519.  
  520.     (*names)[total_widgets] = (*classes)[total_widgets] = NULL;
  521.  
  522.     for ( i = (total_widgets - 1); i >= 0 ; node = node->parent, i--) {
  523.       (*names)[i] = node->name;
  524.       (*classes)[i] = node->class;
  525.     }
  526. }
  527.  
  528. /*    Function Name: HandleGetResources
  529.  *    Description: Gets the resources.
  530.  *    Arguments: event - the information from the client.
  531.  *    Returns: an error message to display.
  532.  */
  533.  
  534. char *
  535. HandleGetResources(event)
  536. Event * event;
  537. {
  538.     GetResourcesEvent * get_event = (GetResourcesEvent *) event;
  539.     char buf[BUFSIZ], * errors = NULL;
  540.     int i;
  541.     WNode * node;
  542.  
  543.     for (i = 0; i < (int)get_event->num_entries; i++) {
  544.     node = FindNode(global_tree_info->top_node,
  545.             get_event->info[i].widgets.ids, 
  546.             get_event->info[i].widgets.num_widgets);
  547.  
  548.     if (node == NULL) {
  549.         sprintf(buf, "Editres Internal Error: Unable to FindNode.\n");
  550.         AddString(&errors, buf); 
  551.         continue;    
  552.     }
  553.  
  554.     if (node->resources != NULL) 
  555.         FreeResources(node->resources);
  556.  
  557.     if (!get_event->info[i].error) {
  558.         node->resources = ParseResources(get_event->info + i, &errors);
  559.         CreateResourceBox(node, &errors);
  560.     }
  561.     else {
  562.         AddString(&errors, get_event->info[i].message);
  563.         AddString(&errors, "\n");
  564.     }
  565.     }
  566.  
  567.     return(errors);
  568. }
  569.  
  570. /*    Function Name: CreateResourceBox
  571.  *    Description: Creates a resource box for the widget specified.
  572.  *    Arguments: node - the node of the widget in question.
  573.  *                 errors - an error string.
  574.  *    Returns: none.
  575.  */
  576.  
  577. void
  578. CreateResourceBox(node, errors)
  579. WNode * node;
  580. char ** errors;
  581. {
  582.     void CreateResourceBoxWidgets();
  583.     WidgetResources * resources = node->resources;
  584.     char ** names, ** cons_names;
  585.     int i;
  586.  
  587.     if (global_resource_box_up) {
  588.     AddString(errors, "Only one Resource Box can be active at a time.");
  589.     return;
  590.     }
  591.     else
  592.     global_resource_box_up = TRUE;
  593.  
  594.     if (resources->num_normal > 0) {
  595.     names = (char **) XtMalloc(sizeof(char *) *
  596.                    (resources->num_normal + 1));
  597.     for (i = 0 ; i < resources->num_normal ; i++) 
  598.         names[i] = resources->normal[i].name;
  599.     names[i] = NULL;
  600.     }
  601.     else
  602.     names = NULL;
  603.  
  604.     if (resources->num_constraint > 0) {
  605.     cons_names = (char **) XtMalloc(sizeof(char *) *
  606.                     (resources->num_constraint + 1));
  607.     
  608.     for (i = 0 ; i < resources->num_constraint ; i++) 
  609.         cons_names[i] = resources->constraint[i].name;
  610.     cons_names[i] = NULL;
  611.     }
  612.     else
  613.     cons_names = NULL;
  614.  
  615.     CreateResourceBoxWidgets(node, names, cons_names);
  616. }
  617.  
  618. /*    Function Name: ParseResources
  619.  *    Description: Parses the resource values returned from the client
  620.  *                   into a resources structure.
  621.  *    Arguments: info - info about a widget's resources.
  622.  *                 error - where to place error info.
  623.  *    Returns: The resource information.
  624.  */
  625.  
  626. static WidgetResources * 
  627. ParseResources(info, error)
  628. GetResourcesInfo * info;
  629. char **error;
  630. {
  631.     WidgetResources * resources;
  632.     WidgetResourceInfo * normal;
  633.     int i;
  634.  
  635.     resources = (WidgetResources *) XtMalloc(sizeof(WidgetResources)); 
  636.     
  637.     /*
  638.      * Allocate enough space for both the normal and constraint resources,
  639.      * then add the normal resources from the top, and the constraint resources
  640.      * from the bottom.  This assures that enough memory is allocated, and
  641.      * that there is no overlap.
  642.      */
  643.  
  644.     resources->normal = (WidgetResourceInfo *) 
  645.                 XtMalloc(sizeof(WidgetResourceInfo) * info->num_resources);
  646.  
  647.     normal = resources->normal;
  648.     resources->constraint = resources->normal + info->num_resources - 1;
  649.  
  650.     resources->num_constraint = resources->num_normal = 0;
  651.  
  652.     for (i = 0; i < (int)info->num_resources; i++) {
  653.     switch((int) info->res_info[i].res_type) {
  654.     case NormalResource:
  655.         resources->num_normal++;
  656.         AddResource(info->res_info + i, normal++);        
  657.         break;
  658.     case ConstraintResource:
  659.         resources->num_constraint++;
  660.         AddResource(info->res_info + i, resources->constraint--);
  661.         break;
  662.     default:
  663.         {
  664.         char buf[BUFSIZ];
  665.         sprintf(buf, "Unknown resource type %d\n", 
  666.             info->res_info[i].res_type);
  667.         AddString(error, buf);
  668.         }
  669.         break;
  670.     }
  671.     }
  672.  
  673.     /*
  674.      * Sort the resources alphabetically. 
  675.      */
  676.  
  677.     qsort(resources->normal, resources->num_normal,
  678.       sizeof(WidgetResourceInfo), CompareResourceEntries);
  679.  
  680.     if (resources->num_constraint > 0) {
  681.     resources->constraint++;
  682.     qsort(resources->constraint, resources->num_constraint,
  683.           sizeof(WidgetResourceInfo), CompareResourceEntries);
  684.     }
  685.     else
  686.     resources->constraint = NULL;
  687.  
  688.     return(resources);
  689. }
  690.  
  691. /*    Function Name: CompareResourceEntries
  692.  *    Description: Compares two resource entries.
  693.  *    Arguments: e1, e2 - the entries to compare.
  694.  *    Returns: an integer >, < or = 0.
  695.  */
  696.  
  697. static int 
  698. CompareResourceEntries(e1, e2) 
  699. WidgetResourceInfo *e1, *e2;
  700. {
  701.     return (strcmp(e1->name, e2->name));
  702. }
  703.  
  704. /*    Function Name: AddResource
  705.  *    Description: Parses the resource string a stuffs in individual
  706.  *                   parts into the resource info struct.
  707.  *    Arguments: res_info - the resource info from the event.
  708.  *                 resource - location to stuff the resource into.
  709.  *    Returns: none.
  710.  */
  711.  
  712. static void
  713. AddResource(res_info, resource) 
  714. ResourceInfo * res_info;
  715. WidgetResourceInfo * resource;
  716. {
  717.     resource->name = res_info->name;
  718.     res_info->name = NULL;    /* Keeps it from being deallocated. */
  719.     resource->class = res_info->class;
  720.     res_info->class = NULL;    /* Keeps it from being deallocated. */
  721.     resource->type = res_info->type;
  722.     res_info->type = NULL;    /* Keeps it from being deallocated. */
  723. }
  724.  
  725.  
  726. /*    Function Name: FreeResources
  727.  *    Description: frees the resource inforation.
  728.  *    Arguments: resources.
  729.  *    Returns: none.
  730.  */
  731.  
  732. static void
  733. FreeResources(resources) 
  734. WidgetResources * resources;
  735. {
  736.     int i;
  737.  
  738.     if (resources->num_normal > 0) {
  739.     for (i = 0; i < resources->num_normal; i++) {
  740.         XtFree(resources->normal[i].name);
  741.         XtFree(resources->normal[i].class);
  742.         XtFree(resources->normal[i].type);
  743.     }
  744.     XFree((char *)resources->normal);
  745.     }
  746.  
  747.     if (resources->num_constraint > 0) {
  748.     for (i = 0; i < resources->num_constraint; i++) {
  749.         XtFree(resources->constraint[i].name);
  750.         XtFree(resources->constraint[i].class);
  751.         XtFree(resources->constraint[i].type);
  752.     }
  753.     XFree((char *)resources->constraint);
  754.     }
  755.  
  756.     XFree((char *)resources);
  757. }
  758.     
  759.  
  760. /*    Function Name: CheckDatabase
  761.  *    Description: Checks to see if the node is in the database.
  762.  *    Arguments: db - the db to check
  763.  *                 names, clases - names and clases, represented as quarks.
  764.  *    Returns: True if this entry is found.
  765.  */
  766.  
  767. Boolean
  768. CheckDatabase(db, names, classes)
  769. XrmDatabase db;
  770. XrmQuarkList names, classes;
  771. {
  772.     XrmRepresentation junk;
  773.     XrmValue garbage;
  774.  
  775.     return(XrmQGetResource(db, names, classes, &junk, &garbage));
  776. }
  777.  
  778. /*    Function Name: Quarkify
  779.  *    Description: Quarkifies the string list specifed.
  780.  *    Arguments: list - list of strings to quarkify
  781.  *                 ptr - an additional string to quarkify.
  782.  *    Returns: none.
  783.  */
  784.  
  785. XrmQuarkList
  786. Quarkify(list, ptr)
  787. char ** list;
  788. char * ptr;
  789. {
  790.     int i;
  791.     char ** tlist;
  792.     XrmQuarkList quarks, tquarks;
  793.  
  794.     for (i = 0, tlist = list; *tlist != NULL; tlist++, i++) {}
  795.     if (ptr != NULL)
  796.     i++;
  797.     i++;            /* leave space for NULLQUARK */
  798.  
  799.     quarks = (XrmQuarkList) XtMalloc(sizeof(XrmQuark) * i);
  800.  
  801.     for (tlist = list, tquarks = quarks; *tlist != NULL; tlist++, tquarks++) 
  802.     *tquarks = XrmStringToQuark(*tlist);
  803.  
  804.     if (ptr != NULL) 
  805.     *tquarks++ = XrmStringToQuark(ptr);
  806.     
  807.     *tquarks = NULLQUARK;
  808.     return(quarks);
  809. }
  810.  
  811. /*    Function Name: ExecuteOverAllNodes
  812.  *    Description: Executes the given function over all nodes.
  813.  *    Arguments: top_node - top node of the tree.
  814.  *                 func - the function to execute.
  815.  *                 data - a data pointer to pass to the function.
  816.  *    Returns: none
  817.  */
  818.  
  819. void
  820. ExecuteOverAllNodes(top_node, func, data)
  821. WNode * top_node;
  822. void (*func)();
  823. XtPointer data;
  824. {
  825.     int i;
  826.  
  827.     (*func)(top_node, data);
  828.  
  829.     for (i = 0; i < top_node->num_children; i++) 
  830.     ExecuteOverAllNodes(top_node->children[i], func, data);
  831. }
  832.  
  833. /*    Function Name: InsertWidgetFromNode
  834.  *    Description: Inserts the widget info for this widget represented
  835.  *                   by this node.
  836.  *    Arguments: stream - the stream to insert it info into.
  837.  *                 none - the widget node to insert.
  838.  *    Returns: none
  839.  */
  840.  
  841. void
  842. InsertWidgetFromNode(stream, node)
  843. ProtocolStream * stream;
  844. WNode * node;
  845. {
  846.     WNode *temp;
  847.     unsigned long * widget_list;
  848.     register int i, num_widgets;
  849.  
  850.     for (temp = node, i = 0; temp != 0; temp = temp->parent, i++) {}
  851.  
  852.     num_widgets = i;
  853.     widget_list = (unsigned long *) 
  854.               XtMalloc(sizeof(unsigned long) * num_widgets);
  855.  
  856.     /*
  857.      * Put the widgets into the list.
  858.      * Make sure that they are inserted in the list from parent -> child.
  859.      */
  860.  
  861.     for (i--, temp = node; temp != 0; temp = temp->parent, i--) 
  862.     widget_list[i] = temp->id;
  863.     
  864.     _XEditResPut16(stream, num_widgets);    /* insert number of widgets. */
  865.     for (i = 0; i < num_widgets; i++)     /* insert Widgets themselves. */
  866.     _XEditResPut32(stream, widget_list[i]);
  867.     
  868.     XtFree((char *)widget_list);
  869. }
  870.  
  871. /*    Function Name: GetFailureMesssage
  872.  *    Description: returns the message returned from a failed request.
  873.  *    Arguments: stream - the protocol stream containing the message.
  874.  *    Returns: message to show.
  875.  */
  876.  
  877. char * 
  878. GetFailureMessage(stream)
  879. ProtocolStream * stream;
  880. {
  881.     char * return_str;
  882.  
  883.     if (_XEditResGetString8(stream, &return_str)) 
  884.     return(return_str);
  885.  
  886.     return(XtNewString("Unable to unpack protocol request."));
  887. }
  888.  
  889. /*    Function Name: ProtocolFailure
  890.  *    Description: Gets the version of the protocol the client is
  891.  *                   willing to speak.
  892.  *    Arguments: stream - the protocol stream containing the message.
  893.  *    Returns: message to show.
  894.  */
  895.  
  896. char * 
  897. ProtocolFailure(stream)
  898. ProtocolStream * stream;
  899. {
  900.     char buf[BUFSIZ];
  901.     unsigned char version;
  902.  
  903.     if (!_XEditResGet8(stream, &version)) 
  904.     return(XtNewString("Unable to unpack protocol request."));
  905.  
  906.     sprintf(buf, "This version of editres uses protocol version %d.\n%s%d",
  907.         CURRENT_PROTOCOL_VERSION,
  908.         "But the client speaks version ", (int) version);
  909.     return(XtNewString(buf));
  910. }
  911.     
  912.